package com.wnzt.baszh.webservice;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

import org.apache.axis.client.Call;
import org.apache.cxf.jaxws.context.WebServiceContextImpl;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.apache.log4j.Logger;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.xml.security.utils.Base64;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.wnzt.baszh.entity.MedicalFile;
import com.wnzt.baszh.entity.MedicalPdf;
import com.wnzt.baszh.service.IArchivingService;
import com.wnzt.baszh.service.impl.MedicalShootService;
import com.wnzt.baszh.util.common.FileEncodeAndDecode;
import com.wnzt.baszh.util.common.FileUtil;
import com.wnzt.baszh.util.common.GlobalFun;
import com.wnzt.baszh.util.common.MD5Util;
import com.wnzt.baszh.util.common.PdfParser;
import com.wnzt.baszh.util.common.SetSystemProperty;
import com.wnzt.baszh.util.common.WebServiceUtil;


@WebService(endpointInterface = "com.wnzt.baszh.webservice.IFileWebService",serviceName = "fileWebService")
public class FileWebServiceImpl implements IFileWebService{

	Logger logger = Logger.getLogger(FileWebServiceImpl.class);
	
	private IArchivingService archivingService;
	
	private MedicalShootService medicalShootService;
	
	@Resource
	public void setArchivingService(IArchivingService archivingService) {
		this.archivingService = archivingService;
	}
	
	@Resource
	public void setMedicalShootService(MedicalShootService medicalShootService) {
		this.medicalShootService = medicalShootService;
	}
	
	@Override
	public String uploadpdf(@WebParam(name="xmlStr")String xmlStr) {
		WebServiceUtil util=new WebServiceUtil();
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		Map<String,String> map=SetSystemProperty.propertiesToMap(path+"/config.properties");
		String strDirPath = getRequest().getSession().getServletContext().getRealPath("/");
		try {
			MedicalFile mf=util.parserUploadPdfXml(xmlStr);
			List<MedicalPdf> pdfs=mf.getMedicalPdfs();
			for (MedicalPdf mp : pdfs) {
				if(GlobalFun.hasValue(mp.getMedicalid())){//有病历id才保存
					//执行将pdf文件上传至服务器
					InputStream fis = new ByteArrayInputStream(mp.getFilebyte());
					String filepath=strDirPath+map.get("archive.pdf.path")+mf.getFprn()+"\\"+mf.getFtimes();
					File file =new File(filepath);    
					//如果文件夹不存在则创建    
					if  (!file .exists()  && !file .isDirectory()){       
					    file .mkdirs();    
					}
					file=new File(filepath+"\\"+mp.getFtitle()+".pdf");    
					if(!file.exists()){    
					    try {    
					        file.createNewFile();    
					    } catch (IOException e) {    
					        e.printStackTrace();    
					    }    
					}
					FileOutputStream os = new FileOutputStream(file);   //文件的输出流文件的路径为fileto 
				    byte[] buffer = new byte[1024];   //定义缓存的字节数组为1K 
				    int len = fis.read(buffer);       //将文件读入字节数组 
				    while (len != -1) { 
				    	os.write(buffer,0,len);       //将文件写到指定的路径下 
				    	len = fis.read(buffer); 
					} 
					fis.close(); 
					os.close(); 
				}
			}
			this.archivingService.addArchived( mf.getFprn(), mf.getFtimes(),"1");
		} catch (Exception e) {
			e.printStackTrace();
			return getResult("102",e.getMessage());
		}
		return getResult("100","成功");
	}
	/**
	* <p>Title: 通用返回</p>
	* <p>Description: </p>
	* @param status
	* @param desc
	* @param data
	* @return
	 */
	public static String getResult(String result,String resultinfo){
		StringBuffer xml=new StringBuffer();
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		xml.append("<data>");
		xml.append("<result>").append(result).append("</result>");
		xml.append("<resultinfo>").append(resultinfo).append("</resultinfo>");
		xml.append("</data>");
		return xml.toString();
	}

	@Override
	public String uploadPDFXH(@WebParam(name="xmlStr",targetNamespace="http://webservice.baszh.wnzt.com/")String xmlStr) {
		System.out.println(xmlStr);
		WebServiceUtil util=new WebServiceUtil();
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		Map<String,String> prop=SetSystemProperty.propertiesToMap(path+"/config.properties");
		String strDirPath = getRequest().getSession().getServletContext().getRealPath("/");
		try {
			//解析
			MedicalFile mf=util.parserUploadPDFXml(xmlStr);
			if(null!=mf.getFilebyte()){//有病历数据流文件
				
				//字节流
				InputStream fis = new ByteArrayInputStream(mf.getFilebyte());
				
				//临时保存目录：本地路径\住院号\(或\\病案号\\住院次数)
				String temppath=prop.get("archive.pdf.temp.path")+Calendar.getInstance().getTimeInMillis();
				util.CreateMultilayerFile(temppath);//创建临时文件目录
				String tempFile=temppath+"\\"+Calendar.getInstance().getTimeInMillis()+".pdf";
				
				//创建临时文件
				FileUtil.createFile(tempFile);
				//输出到临时文件----开始
				FileOutputStream os = new FileOutputStream(new File(tempFile));   //文件的输出流文件的路径为fileto 
			    byte[] buffer = new byte[1024];   //定义缓存的字节数组为1K 
			    int len = fis.read(buffer);       //将文件读入字节数组 
			    while (len != -1) { 
			    	os.write(buffer,0,len);       //将文件写到指定的路径下 
			    	len = fis.read(buffer); 
				} 
				fis.close(); 
				os.close(); 
				/**将文件字节流进行读取*/
				Map<String,Object> par=new HashMap<String,Object>();
				//输出到临时文件----结束
				
				
				if(GlobalFun.hasValue(mf.getFtitle())){
					//文件名格式  文件名_住院号.pdf||文件名_病案号_住院次数.pdf
					String [] arr=mf.getFtitle().substring(0,mf.getFtitle().lastIndexOf(".")).split("_");
					if(arr.length==2){//住院号
						par.put("zyid", arr[1]);
					}else if(arr.length==3){//病案号+住院次数
						par.put("prn", arr[1]);
						par.put("times", arr[2]);
					}
				}
				if(!GlobalFun.hasValue(par.get("zyid")) && (!GlobalFun.hasValue(par.get("prn"))||!GlobalFun.hasValue(par.get("times")))){
					par=PdfParser.parser(tempFile);
				}
				//加密后保存目录：本地路径\住院号\(或\\病案号\\住院次数)
				String encryptpath=prop.get("archive.pdf.encrypt.path")+par.get("zyid");
				if(!GlobalFun.hasValue(par.get("zyid"))){
					encryptpath=prop.get("archive.pdf.encrypt.path")+par.get("prn")+"\\"+par.get("times");
					if(!GlobalFun.hasValue(par.get("prn"))){
						return getResult("102", "上传文档未解析到病案号。");
					}
					if(!GlobalFun.hasValue(par.get("times"))){
						return getResult("102", "上传文档未解析到住院次数。");
					}
				}
				util.CreateMultilayerFile(encryptpath);//创建加密文件目录
				String encryptFile=encryptpath+"\\"+par.get("filename")+".pdf";
				
				/*对文件进行加密保存*/
        		new FileEncodeAndDecode(prop.get("encrypt.key")).encrypt(tempFile,encryptFile);
				
        		par.put("filehash", MD5Util.getMD5Checksum(tempFile));
        		par.put("filehashsign", mf.getFfilehashsign());
        		par.put("encryptFile", encryptFile);
        		//保存归档
				this.archivingService.saveArchived(par);
				
				//删除临时文件
        		FileUtil.deleteFile(tempFile);
        		//删除临时文件
        		FileUtil.deleteDirectory(temppath);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return getResult("102",e.getMessage());
		}
		return getResult("100","成功");
	}

	@Override
	public String BrowseArchive(@WebParam(name="xmlStr")String xmlStr) {
		//System.out.println("参数:"+xmlStr);

		System.out.println("集中浏览归档时间："+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
    	Map<String,String> map=SetSystemProperty.propertiesToMap(path+"/config.properties");
    	String strDirPath = getRequest().getSession().getServletContext().getRealPath("/");
    	PDDocument document = null;
    	try {
    		WebServiceUtil util=new WebServiceUtil();
			Call call = util.getMedicalCall();// 获取medical WebServer连接
			//解析传入参数
			MedicalFile param=util.parserBrowseArchiveXml(xmlStr);
			//获取全部电子病历
			String outParamXml = (String) call.invoke(new Object[] { xmlStr }); // 获取返回结果
			//解析全部电子病历返回
			List<MedicalFile> medicalFileList = util.parserMedicalFilelistResultXml(outParamXml);
			for (MedicalFile mf : medicalFileList) {
				if(!GlobalFun.hasValue(mf.getFpdfpath())){//没有pdf才去接口获取pdf文件
					//有需要获取的pdf才连接
					param.setMedicalid(mf.getMedicalid());
					call = util.getMedicalPdfCall();// 获取pdf WebServer连接
					String inParamXml=util.getMedicalPdfParamStr(param);//入参转换为xml格式
					outParamXml = (String) call.invoke(new Object[] { inParamXml }); //获取返回结果
					List<MedicalPdf> medicalPdfs = util.parserMedicalPdfResultXml(outParamXml);
					for (MedicalPdf mp : medicalPdfs) {
						if(GlobalFun.hasValue(mp.getFpath())||null!=mp.getFilebyte()){//电子病历PDF文件流，fpath和filebyte其中一个必须非空
							
							//有病历id才保存
							//执行将pdf文件上传至服务器
							InputStream fis = new ByteArrayInputStream(mp.getFilebyte());
							//本地路径\病案号\住院次数\病历类型\
							String filepath=strDirPath+map.get("archive.pdf.path")+param.getFprn()+"\\"+param.getFtimes();
							util.CreateMultilayerFile(filepath);//创建多级目录
							File file =new File(filepath);    
							//如果文件夹不存在则创建    
							if  (!file .exists()  && !file .isDirectory()){       
							    file .mkdir();    
							}
							file=new File(filepath+"\\"+mf.getFtitle()+".pdf");    
							if(!file.exists()){    
							    try {    
							        file.createNewFile();    
							    } catch (IOException e) {    
							        e.printStackTrace();    
							    }    
							}
							FileOutputStream os = new FileOutputStream(file);   //文件的输出流文件的路径为fileto 
						    byte[] buffer = new byte[1024];   //定义缓存的字节数组为1K 
						    int len = fis.read(buffer);       //将文件读入字节数组 
						    while (len != -1) { 
						    	os.write(buffer,0,len);       //将文件写到指定的路径下 
						    	len = fis.read(buffer); 
							} 
							fis.close(); 
							os.close(); 
							String pdfFile=map.get("archive.pdf.path")+param.getFprn()+"/"+param.getFtimes()+"/"+mf.getFtitle()+".pdf";
							// 方式二：
				            document=PDDocument.load(file);
				            // 获取页码
				            int pages = document.getNumberOfPages();
							//将归档信息保存至数据库
							this.archivingService.addArchived(param.getFprn(), param.getFtimes(),"0");
							this.archivingService.addBagdmx(param.getFprn(), param.getFtimes(), mf.getFtitle(), mf.getFtype()+"", pages+"", pdfFile);
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "500";  // 500 : 程序执行失败
		} 
    	return "200"; // 200 : 程序执行成功
	}

	@Override
	public String getMedicalFileList(@WebParam(name="xmlStr")String xmlStr) {
		WebServiceUtil util=new WebServiceUtil();
		try {
			//解析传入参数
			Document document = DocumentHelper.parseText(xmlStr);
			if (document == null)
				return getResult("102", "参数有误.");
			
			Element rootElement = document.getRootElement();
			String fzyid = rootElement.element("fzyid").getTextTrim();
			String fprn = rootElement.element("fprn").getTextTrim();
			String ftimes = rootElement.element("ftimes").getTextTrim();
			String fname = rootElement.element("fname").getTextTrim();
			//模拟返回数据
			StringBuffer xml=new StringBuffer();
			xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			xml.append("<data>");
			xml.append("<result>").append(100).append("</result>");
			xml.append("<resultinfo>").append("成功").append("</resultinfo>");
			List<Map<String, Object>> listOptions = medicalShootService.getListOptions(); // 查询病案信息展示列表项
			for (Map<String, Object> map : listOptions) {
				xml.append("<medicalfile>");
					xml.append("<medicalid>").append(map.get("FNAME")).append("</medicalid>");
					xml.append("<ftype>").append(map.get("FTYPE")).append("</ftype>");
					xml.append("<ftitle>").append(map.get("FNAME")).append("</ftitle>");
					xml.append("<fpdfpath/>");
				xml.append("</medicalfile>");
			}
			xml.append("</data>");
			return xml.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return getResult("102", e.getMessage());
		}
	}

	@Override
	public String getPdf(@WebParam(name="xmlStr")String xmlStr) {
		try {
			//解析传入参数
			Document document = DocumentHelper.parseText(xmlStr);
			if (document == null)
				return getResult("102", "参数有误.");
			
			Element rootElement = document.getRootElement();
			String fzyid = rootElement.element("fzyid").getTextTrim();
			String fprn = rootElement.element("fprn").getTextTrim();
			String ftimes = rootElement.element("ftimes").getTextTrim();
			String fname = rootElement.element("fname").getTextTrim();
			String medicalids=rootElement.element("medicalids").getTextTrim();
			String [] medicalidArr=medicalids.split(",");
			//模拟返回数据
			StringBuffer xml=new StringBuffer();
			xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			xml.append("<data>");
			xml.append("<result>").append(100).append("</result>");
			xml.append("<resultinfo>").append("成功").append("</resultinfo>");
			for (String medicalid : medicalidArr) {
				String filepath="D:\\dzbl\\pdf\\"+fprn+"\\"+ftimes+"\\"+medicalid+".pdf";
				File file =new File(filepath);
				if(file.exists()){//存在读取返回
					String filebyte=getFileByteString(file);
					xml.append("<medicalpdf>");
						xml.append("<medicalid>").append(medicalid).append("</medicalid>");
						xml.append("<fpath>").append("").append("</fpath>");
						xml.append("<filebyte>").append(filebyte).append("</filebyte>");
					xml.append("</medicalpdf>");
				}
			}
			xml.append("</data>");
			return xml.toString();
		} catch (DocumentException e) {
			e.printStackTrace();
			return getResult("102", e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			return getResult("102", e.getMessage());
		}
	}

	/**
	 * @author [lv tang wei]
	 * Describe:读取文件用Base64将其转化为字符串
	 * @param file
	 * @return
	 * @throws Exception
	 * [2017年5月24日]
	 */
	private String getFileByteString(File file) throws Exception{
	    InputStream in = new FileInputStream(file);
	    // 取得文件大小
	    long length = file.length();
	    // 根据大小创建字节数组
	    byte[] bytes = new byte[(int) length];
	    // 读取文件内容到字节数组
	    int offset = 0;
	    int numRead = 0;
	    while (offset < bytes.length
	        && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
	      offset += numRead;
	    }
	    // 读取完毕的校验  
	    if (offset < bytes.length) {
	    	throw new IOException("不能完全读取文件："+ file.getName());
	    }
	    in.close();
	    String encodedFileString = Base64.encode(bytes);
	    return encodedFileString;
	}

	/**
	 * 取request
	 * @author [lv tang wei]
	 * Describe:
	 * @return
	 * [2017年7月5日]
	 */
	public HttpServletRequest getRequest(){
		WebServiceContext context = new WebServiceContextImpl();
		MessageContext ctx = context.getMessageContext();
		HttpServletRequest request = (HttpServletRequest) ctx.get(AbstractHTTPDestination.HTTP_REQUEST);
		return request;
	}
}
